import gnu.io.CommPortIdentifier;

import java.awt.AWTException;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;

import javax.imageio.ImageIO;

public class BluetoothComm implements Runnable
{
	private byte[][] imagebin;
	private BufferedImage image;
	private Serial_Base mbase;
	private int typebyte;
	private boolean isActive;
	private boolean debug = false;
	private int buf;
	private boolean first = true;
	private boolean update = true;
	private String COM = null;
	SlideShowServer mMain;

	//コンストラクタ
	BluetoothComm(SlideShowServer main)
	{
		mMain = main;
	}

	//イメージ情報転送
	public void sendImageInfo(int w, int h,int format,int size)
	{
		String sendstr = common.ACCEPT_SEND_MESSAGE+"(w:"+w+",h:"+h+",pix:"+format+",s:"+size+")\r\n";
		mbase.Serial_puts(sendstr);
	}

	//準備完了メッセージ取得
	public void recieveReadyMessage()
	{
		String str = "";
		String check = common.IMAGEINFO_RECIEVE_MESSAGE;
		while(true)
		{
			str = mbase.Serial_read();
			if(str == null)continue;
			else if(str.equals(check))break;
		}
	}

	//データの受信メッセージ取得
	public void reciveDataMessage()
	{
		//mbase.Serial_puts(common.IMAGE_SEND_MESSAGE);
		sendData();
	}

	//画像データ転送(16Kbyteごとに転送しかできない(ライブラリの仕様))
	public void sendData()
	{
		int i = 0;
		for(i=0;i<imagebin[buf].length/common.SERIAL_MAX_CHAR_SIZE;i++)
		{
			System.out.println(i*common.SERIAL_MAX_CHAR_SIZE+"+"+common.SERIAL_MAX_CHAR_SIZE);
			mbase.Serial_write(imagebin[buf],i*common.SERIAL_MAX_CHAR_SIZE,common.SERIAL_MAX_CHAR_SIZE);
		}
		System.out.println((i*common.SERIAL_MAX_CHAR_SIZE)+"+"+(imagebin[buf].length-i*common.SERIAL_MAX_CHAR_SIZE));
		mbase.Serial_write(imagebin[buf],i*common.SERIAL_MAX_CHAR_SIZE, imagebin[buf].length - i*common.SERIAL_MAX_CHAR_SIZE);
		buf = (buf+1)%common.BUFFER_SIZE;
		update = true;
	}

	// デバッグ用BMP読み込み
	public void readBMP() {
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			BufferedOutputStream os = new BufferedOutputStream(bos);

			//画像取得
			image = ImageIO.read(new File("C:/Users/muchiki0226/Desktop/test.bmp"));
			image.flush();
			os.flush();
			os.close();

			//イメージのリサイズ(アスペクト比維持)
			int width = common.IMAGE_MAX_WIDTH;
			int height = (int)(((double)width / image.getWidth()) * (double)image.getHeight());

			BufferedImage resizeImage = new BufferedImage(width, height, image.getType());

			/*
			AffineTransformOp ato = new AffineTransformOp(
	                   AffineTransform.getScaleInstance((double)width / image.getWidth(),
					                                    (double) height / image.getHeight()),
					                                    null);
			ato.filter(image, resizeImage);
			*/
			resizeImage.getGraphics().drawImage(
	                  image.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING),
	                    0, 0, width, height, null);
			image = resizeImage;

			//イメージのフォーマット変更
			ImageIO.write(resizeImage, "png", os);

			System.out.println(bos.toByteArray().length);

			//画像データをバイナリに変更
			if(first)
			{
				imagebin = new byte[common.BUFFER_SIZE][bos.toByteArray().length];
				first = false;
			}
			imagebin[buf] = bos.toByteArray();

			//画素フォーマット取得
			switch(image.getType())
			{
			case BufferedImage.TYPE_3BYTE_BGR:
				typebyte = 3;
				break;
			case BufferedImage.TYPE_4BYTE_ABGR:
			case BufferedImage.TYPE_4BYTE_ABGR_PRE:
				typebyte = 4;
				break;
			default:
				typebyte = 0;
				break;
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	//画面キャプチャ
	public void readDisplayCapture()
	{
		Robot robot;
		try {
			robot = new Robot();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			BufferedOutputStream os = new BufferedOutputStream(bos);

			image = robot.createScreenCapture(new Rectangle(0, 0, Toolkit.getDefaultToolkit().getScreenSize().width,Toolkit.getDefaultToolkit().getScreenSize().height));
			System.out.println("Size:"+Toolkit.getDefaultToolkit().getScreenSize().width+","+Toolkit.getDefaultToolkit().getScreenSize().height);
			image.flush();
			os.flush();
			os.close();


			//イメージのリサイズ(アスペクト比維持)
			int width = common.IMAGE_MAX_WIDTH;
			int height = (int)(((double)width / image.getWidth()) * (double)image.getHeight());

			BufferedImage resizeImage = new BufferedImage(width, height, image.getType());
			//resizeImage.getGraphics().drawImage(image.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING),0, 0, width, height, null);

			AffineTransformOp ato = new AffineTransformOp(
	                   AffineTransform.getScaleInstance((double)width / image.getWidth(),
					                                    (double) height / image.getHeight()),
					                                    null);
			ato.filter(image, resizeImage);

			image = resizeImage;
			//イメージのフォーマット変更
			ImageIO.write(image, "png", os);

			/*
			// 以下、出力処理
			String dirName = "C:/Users/muchiki0226/Desktop/";
			String fileName = "test.png";
			ImageIO.write(image, "png", new File(dirName, fileName));
			 */

			System.out.println(bos.toByteArray().length);
			if(first)
			{
				imagebin = new byte[common.BUFFER_SIZE][bos.toByteArray().length];
				first = false;
			}
			imagebin[buf] = bos.toByteArray();

			switch(image.getType())
			{
			case BufferedImage.TYPE_3BYTE_BGR:
				typebyte = 3;
				break;
			case BufferedImage.TYPE_4BYTE_ABGR:
			case BufferedImage.TYPE_4BYTE_ABGR_PRE:
				typebyte = 4;
				break;
			default:
				typebyte = 0;
				break;
			}
			System.out.println(typebyte);
		} catch (AWTException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
	}

	public void setCOMNumber(String str)
	{
		COM = str;
	}

	@Override
	public void run()
	{
		isActive = true;
		buf = 0;
		mbase = new Serial_Base();
		if(mbase.Serial_open(COM,common.SERIAL_BOUDRATE))
		{
			mMain.setConnectImage();
			while(isActive)
			{
				if(!mbase.Serial_available())
				{
					continue;
				}

				if(update)
				{
					if(debug)
					{
						readBMP();
					}
					else
					{
						readDisplayCapture();
					}
					update = false;
				}

				String str = mbase.Serial_read();
				if(str.equals(common.IMAGEINFO_RECIEVE_MESSAGE))
				{
					System.out.println(str);
					sendImageInfo(image.getWidth(),image.getHeight(),typebyte,imagebin[buf].length);
				}
				else if(str.equals(common.IMAGE_RECIEVE_MESSAGE))
				{
					System.out.println(str);
					reciveDataMessage();
				}
			}

			mbase.Serial_close();
			mMain.setDisConnectImage();
		}
	}

	public void destroyThread()
	{
		if(isActive)
		{
			isActive = false;
		}
	}
}